#include "ClientFunc.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int LoginFace()
{
    printf("=======================聊天室登录====================\n");
    printf("1. 注册 \n");
    printf("2. 登录 \n");
    printf("====================================================\n");
    printf(" 请选择你要的功能 \n");
    int choice = 0;
    scanf("%d", &choice);

    return choice * (-1);
}

int Interface()
{
    printf("=======================WELCOME CHAT ROOM====================\n");
    printf("1. 私聊 \n");
    printf("2. 广播 \n");
    printf("3. 查看在线用户 \n");
    printf("4. 文件发送 \n");
    printf("5. 我的网盘 \n");
    printf("============================================================\n");
    printf(" 请选择你要的功能 \n");
    int choice = 0;
    scanf("%d", &choice);

    return choice;
}

// 注册
MSG SignUp(char * MyName)
{
    MSG m;
    m.flag = SIGUP;// 注册用户名
    printf("=========================注册新用户==========================\n");
    printf("请输入你的用户名：\n");
    scanf("%s", m.FromName);
    printf("请输入你的密码：\n");
    scanf("%s", m.Content);
    printf("============================================================\n");
    strcpy(MyName, m.FromName);
    return m;
}

// 是否注册成功
bool IsSignUpSuccess(MSG *m)
{
    if (strcmp(m->Content, "注册成功") == 0)
    {
        printf("注册成功！欢迎来到聊天室\n");
        return true;
    }
    else
    {
        printf("注册错误:%s\n", m->Content);
        return false;
    }
}

// 登录
MSG Login(char *MyName)
{
    MSG m;
    m.flag = LOGIN;// 登录
    printf("=========================登陆该用户==========================\n");
    printf("请输入你的用户名：\n");
    scanf("%s", m.FromName);
    printf("请输入你的密码：\n");
    scanf("%s", m.Content);
    printf("============================================================\n");
    strcpy(MyName, m.FromName);
    return m;
}

// 是否登录成功
bool IsLoginSuccess(MSG *m)
{
    if (strcmp(m->Content, "登陆成功") == 0)
    {
        printf("登录成功！欢迎来到聊天室\n");
        return true;
    }
    else
    {
        printf("登录错误:%s\n", m->Content);
        return false;
    }
}

// 群聊的逻辑 更简单
MSG ChatBroadCast()
{
    MSG m;
    m.flag = BROADCAST;// 标志位
    printf("请输入你要发送的信息：\n");
    scanf("%s", m.Content);
    
    return m;
}

// 查看在线用户
MSG GetServerOnlineList()
{
    MSG m;
    m.flag = ONLINELIST;

    return m;
}

// 私聊的逻辑
MSG ChatToClient()
{
    MSG m;
    m.flag = CHAT;// 标志位
    printf("请输入你要发送的用户名称：\n");
    scanf("%s", m.ToName);
    printf("请输入你要发送的信息：\n");
    scanf("%s", m.Content);
    return m;
}

// 解析用户列表字符串
void ShowOnlineList(MSG *m)
{
    char str[ContentSize] = { 0 };
    strcpy(str, m->Content);
    char *dest = strtok(str, ",");// 切割字符串
    int count = 1;
    while(dest != NULL)
    {
        printf("%d : %s\n", count++, dest);
        dest = strtok(NULL, ",");// 持续切割
    }
}

// 文件发送
MSG SendFile()
{
    MSG m;
    m.flag = SENDFILE;
    printf("请输入你要发送的文件路径:\n");
    scanf("%s", m.Content);
    printf("请输入你要发送用户:\n");
    scanf("%s", m.ToName);
    return m;
}

// 获取文件名称：字符串切割
char *GetFileNameFromPath(const char *filePath)
{
    char str[ContentSize] = { 0 };
    strcpy(str, filePath);

    char* dest = strtok(str, "/");// 按 / 进行切割
    char* fileName = NULL;// 接最后的值
    while(dest != NULL)
    {
        fileName = dest;
        dest = strtok(NULL, "/");
    }
    char *result = strdup(fileName);// 在 堆 上复制字符串，最后记得 free 掉
    
    return result;
}

// 写数据到本地文件
void WriteToLocal(MSG *m)
{
    // 把文件大小、文件名拿出来
    int size = 0;
    memcpy(&size, m->Content, sizeof(int));
    char fileName[NameSize] = { 0 };
    strcpy(fileName, m->Content + 4);
    // 把文件内容拿出来
    char filePath[ContentSize] = { 0 };
    sprintf(filePath, "./%s", fileName);// 默认下载到当前目录下
    FILE *f = fopen(filePath, "a");// 追加写
    fwrite(m->Content + 24, size, 1, f);
    fclose(f);

}


// 网盘界面
int CloudInitface()
{
    printf("==========我的网盘===========\n");
    printf("1. 查看网盘文件\n");
    printf("2. 上传文件\n");
    printf("3. 下载文件\n");
    printf("4. 退回到主界面\n");
    printf("============================\n");

    printf("请输入你的选择：\n");
    int choice = 0;
    scanf("%d", &choice);
    return FILELIST + choice - 1;
}

// 上传文件
MSG UploadFile()
{
    MSG m;
    m.flag = UPLOAD;
    printf("请输入要上传的文件路径\n");
    scanf("%s", m.Content);
    return m;
}

// 拆解:字符串数组
char** Split(const char *str, const char *delim,int *size)
{
    char *splitstr = strdup(str);// 复制一份

    char** result = (char **)malloc(sizeof(char*) * 50);// 分配一个指针数组
    if (result == NULL)
    {
        printf("Splite malloc error\n");
        return NULL;
    }

    int count = 0;
    char *dest = strtok(splitstr, delim);// 按 分隔符 进行切割
    while(dest != NULL)
    {
        result[count++] = strdup(dest);// 复制一份切割后的结果,把切割后的结果存入数组中
        dest = strtok(NULL, delim);// 持续切割
    }

    free(splitstr);
    *size = count;// 返回切割后的结果个数
    return result;
}

// 释放
void FreeStrList(char **strList, int size)
{
    for (int i = 0; i < size; i++)
    {
        // 释放字符串
        free(strList[i]);
    }

    // 释放数组
    free(strList);
}


// 显示文件列表
void ShowFileList(MSG *m)
{
    if (strcmp(m->Content, "getFILELISTERROR") == 0)
    {
        printf("获取网盘文件列表失败\n");
        return;
    }
    int fileCount = 0;
    char **file = Split(m->Content, ",", &fileCount);// 切割字符串
    for (int i = 0; i < fileCount; i++)
    {
        int count = 0;
        char** fileInfo = Split(file[i], ";", &count);// 再次切割
        if (count == 2)
        {
            printf("文件名：%s, 文件大小：%s\n", fileInfo[0], fileInfo[1]);
            FreeStrList(fileInfo, count); 
        }
        else
        {
            FreeStrList(fileInfo, count);
            continue;
        }
    }
    FreeStrList(file, fileCount);// 释放文件列表
}

// 分包的结构体
struct PacketFile
{
    FILE *f;// 文件指针不能少
    long FileSize;
    long currentPosition;

};

// 初始化
PacketFile *PacketFileInit(const char *FilePath)
{
    PacketFile *pf = (PacketFile *)malloc(sizeof(PacketFile));
    if (pf == NULL)
    {
        printf(" PackFileInit malloc error \n");
        return NULL;
    }

    pf->f = fopen(FilePath, "r");// 以只读形式打开文件,权限要以最小权限进行读取
    if (pf->f == NULL)
    {
        printf("打开[%s]文件失败！\n", FilePath);
        free(pf);
        return NULL;
    }
    // 打开成功
    // 先计算文件大小：先把光标移到最后
    fseek(pf->f, 0, SEEK_END);
    pf->FileSize = ftell(pf->f);
    fseek(pf->f, 0, SEEK_SET);// 把文件指针再塞回初始位置

    pf->currentPosition = 0;// 从当前位置开始我们去计算

    return pf;
}

void ReadFromFile(PacketFile *f, void *p, int *size)// 为什么要传一个int *指针，因为我就可以读到实际传过来的字节
{
    // 文件超了
    if (*size + f->currentPosition > f->FileSize)
    {
        *size = f->FileSize - f->currentPosition;// 重新赋值
    }

    fread(p, *size, 1, f->f);
    f->currentPosition += *size;// 一包一包读
}

bool IsFileEnd(PacketFile *f)
{

    return f->currentPosition == f->FileSize;// 当前位置等于已读取文件的大小
}

void ClearPacketFile(PacketFile *f)
{
    fclose(f->f);
    free(f);
}
